package com.siyoumi.app.modules.app_ess.service;

import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.app_ess.entity.EnumEssFileType;
import com.siyoumi.app.modules.app_ess.vo.*;
import com.siyoumi.app.modules.fun.service.SvcFun;
import com.siyoumi.app.modules.fun.vo.VaFunAdd;
import com.siyoumi.app.service.*;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XEnumBase;
import com.siyoumi.component.XSpringContext;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.service.IWebService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

//学习任务
@Slf4j
@Service
public class SvcEssStudy
        implements IWebService {
    static public SvcEssStudy getBean() {
        return XSpringContext.getBean(SvcEssStudy.class);
    }

    static public EssStudyService getApp() {
        return EssStudyService.getBean();
    }


    /**
     * 任务状态
     *
     * @param entity
     */
    public XReturn getState(EssStudy entity) {
        if (XDate.now().isBefore(entity.getEstudy_date_begin())) {
            return XReturn.getR(20040, "未开始");
        }

        if (XDate.now().isAfter(entity.getEstudy_date_end())) {
            return XReturn.getR(20050, "已结束");
        }

        return EnumSys.OK.getR("进行中");
    }

    /**
     * 指定老师
     * 每个模块设置的学习任务数量
     *
     * @param uidTeacher
     */
    public Map<String, Long> moduleTotal(String uidTeacher) {
        JoinWrapperPlus<EssStudy> query = listQuery();
        query.eq("estudy_uid", uidTeacher);
        query.groupBy("estudy_module_id");
        query.select("estudy_module_id", "COUNT(*) total");

        Map<String, Long> data = new HashMap<>();
        List<Map<String, Object>> list = getApp().getMaps(query);
        for (Map<String, Object> item : list) {
            String moduleId = (String) item.get("estudy_module_id");
            Long total = (Long) item.get("total");

            data.put(moduleId, total);
        }
        return data;
    }

    public JoinWrapperPlus<EssStudy> listQuery() {
        return listQuery(InputData.getIns());
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<EssStudy> listQuery(InputData inputData) {
        String name = inputData.input("name");
        String moduleId = inputData.input("module_id");

        JoinWrapperPlus<EssStudy> query = getApp().join();
        query.eq("estudy_x_id", XHttpContext.getX())
                .eq("estudy_del", 0);
        query.orderByDesc("estudy_id");

        if (XStr.hasAnyText(name)) { //名称
            query.like("estudy_name", name);
        }
        if (XStr.hasAnyText(moduleId)) { //场景ID
            query.eq("estudy_module_id", moduleId);
        }

        return query;
    }


    /**
     * 学习任务列表
     *
     * @param studyIds
     */
    public List<EssStudyTask> getTaskList(List<String> studyIds) {
        if (studyIds.isEmpty()) {
            return new ArrayList<>();
        }

        JoinWrapperPlus<EssStudyTask> query = listTaskQuery(studyIds);
        return EssStudyTaskService.getBean().get(query);
    }

    /**
     * 子任务
     *
     * @return query
     */
    public JoinWrapperPlus<EssStudyTask> listTaskQuery(List<String> studyIds) {
        JoinWrapperPlus<EssStudyTask> query = EssStudyTaskService.getBean().join();
        query.in("estask_study_id", studyIds);

        return query;
    }

    /**
     * 学生完成任务记录
     *
     * @param studyIds
     * @param uid
     */
    public List<Map<String, Object>> getRecordList(List<String> studyIds, String uid) {
        if (studyIds.isEmpty()) {
            return new ArrayList<>();
        }

        String[] select = {
                "esre_id",
                "esre_uid",
                "esre_fun",
                "esre_study_id",
                "esre_state",
                "esre_state_date",
                "estask_key",
        };
        JoinWrapperPlus<EssStudyRecord> query = listRecordQuery(InputData.getIns());
        query.join(EssStudyTask.table(), EssStudyTask.tableKey(), "esre_task_id");
        query.eq("esre_uid", uid)
                .in("esre_study_id", studyIds);
        query.select(select);

        return EssStudyRecordService.getBean().getMaps(query);
    }

    /**
     * 记录
     *
     * @return query
     */
    public JoinWrapperPlus<EssStudyRecord> listRecordQuery(InputData inputData) {
        String studyId = inputData.input("study_id");
        String taskId = inputData.input("task_id");
        String classId = inputData.input("class_id");
        String state = inputData.input("state");
        String uid = inputData.input("uid");


        JoinWrapperPlus<EssStudyRecord> query = EssStudyRecordService.getBean().join();
        query.eq("esre_x_id", XHttpContext.getX());

        if (XStr.hasAnyText(studyId)) { //学习任务ID
            query.eq("esre_study_id", studyId);
        }
        if (XStr.hasAnyText(taskId)) { //子任务ID
            query.eq("esre_task_id", taskId);
        }
        if (XStr.hasAnyText(classId)) { //班级ID
            query.eq("esre_class_id", classId);
        }
        if (XStr.hasAnyText(state)) { //完成状态
            query.eq("esre_state", state);
        }
        if (XStr.hasAnyText(uid)) { //学生uid
            query.eq("esre_uid", uid);
        }

        return query;
    }

    /**
     * 添加学习任务
     *
     * @param vo
     */
    @Transactional(rollbackFor = Exception.class)
    public XReturn add(VoEssStudyAdd vo) {
        if (vo.getClass_ids().isEmpty()) {
            return EnumSys.ARR_SIZE_0.getR("请选择班级");
        }
        if (vo.getClass_ids().size() > 5) {
            return EnumSys.ARR_SIZE_0.getR("选择班级数量不能大于5");
        }
        if (vo.getTypes().isEmpty()) {
            return EnumSys.ARR_SIZE_0.getR("请选择类型");
        }

        EnumEssFileType enumfileType = XEnumBase.of(EnumEssFileType.class);
        enumfileType.put("test1", "理论实训");
        enumfileType.put("module", "场景练习");
        for (VoEssStudyAddType item : vo.getTypes()) {
            if (!enumfileType.containsKey(item.getType())) {
                return EnumSys.ENV_ERR.getR("类型异常，" + item.getType());
            }
        }

        //获取班级的所有学生
        JoinWrapperPlus<EssClassUser> query = SvcEssClass.getBean().listUserQuery();
        query.in("ecu_class_id", vo.getClass_ids())
                .eq("ecu_user_type", 0);
        query.select("ecu_uid", "ecu_class_id");
        List<Map<String, Object>> listStudent = EssClassUserService.getBean().getMaps(query);
        List<String> studentUids = listStudent
                .stream().map(item -> (String) item.get("ecu_uid"))
                .collect(Collectors.toList());
        if (studentUids.isEmpty()) {
            XValidator.err(EnumSys.ARR_SIZE_0.getR("学生数量为0"));
        }

        EssStudy entity = new EssStudy();
        XBean.copyProperties(vo, entity);
        entity.setEstudy_x_id(XHttpContext.getX());
        entity.setEstudy_student_total((long) studentUids.size());
        entity.setAutoID();
        getApp().save(entity);

        //分类保存
        List<EssStudyTask> listTask = new ArrayList<>();
        for (VoEssStudyAddType item : vo.getTypes()) {
            EssStudyTask entityTask = new EssStudyTask();
            entityTask.setEstask_study_id(entity.getKey());
            entityTask.setEstask_key(item.getType());
            entityTask.setEstask_fun(item.getFun());
            entityTask.setEstask_x_id(entity.getEstudy_x_id());
            entityTask.setEstask_total((long) studentUids.size());
            entityTask.setAutoID();

            listTask.add(entityTask);
        }
        EssStudyTaskService.getBean().saveBatch(listTask);

        //保存学生记录
        {
            List<EssStudyRecord> listRecord = new ArrayList<>();
            List<EssStudyStudent> listStu = new ArrayList<>();
            for (String uid : studentUids) {
                //学生学习任务领取记录，1学生1条
                EssStudyStudent entityStu = new EssStudyStudent();
                entityStu.setEsstu_x_id(entity.getEstudy_x_id());
                entityStu.setEsstu_uid(uid);
                entityStu.setEsstu_study_id(entity.getKey());
                entityStu.setAutoID();
                listStu.add(entityStu);

                //获取班级ID
                Map<String, Object> mapStudent = listStudent.stream()
                        .filter(item -> item.get("ecu_uid").equals(uid))
                        .findFirst()
                        .orElse(null);
                if (mapStudent == null) {
                    XValidator.err(20254, "找不到班级，" + uid);
                }
                String classId = (String) mapStudent.get("ecu_class_id");
                //学生类型完成情况，1学生1类型1条
                for (EssStudyTask entityTask : listTask) {
                    VoEssStudyAddType voType = vo.getTypes().stream()
                            .filter(item -> item.getType().equals(entityTask.getEstask_key()))
                            .findFirst().orElse(null);

                    EssStudyRecord entityRecord = new EssStudyRecord();
                    entityRecord.setEsre_x_id(XHttpContext.getX());
                    entityRecord.setAutoID();
                    entityRecord.setEsre_study_id(entityTask.getEstask_study_id());
                    entityRecord.setEsre_task_id(entityTask.getKey());
                    entityRecord.setEsre_task_key(entityTask.getEstask_key());
                    entityRecord.setEsre_uid(uid);
                    entityRecord.setEsre_fun(voType.getFun());
                    entityRecord.setEsre_class_id(classId);

                    listRecord.add(entityRecord);
                }
            }

            EssStudyRecordService.getBean().saveBatch(listRecord);
            EssStudyStudentService.getBean().saveBatch(listStu);
        }
        //更新学习任务数量
        updateModuleStudyTotal(vo.getEstudy_module_id());

        XReturn r = EnumSys.OK.getR();
        r.setData("entity", entity);
        return r;
    }

    /**
     * 删除
     */
    @SneakyThrows
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn delete(String id, Boolean admin) {
        EssStudy entity = getApp().getEntity(id);
        XValidator.isNull(entity, "id error");

        XReturn r = getState(entity);
        if (!admin) { //非后台删除
            if (!entity.getEstudy_uid().equals(getUid())) {
                return XReturn.getR(20320, "非本人创建无法删除");
            }

            if (r.getErrCode() != 20040) { //未开始才可以删除
                return XReturn.getR(20330, r.getErrMsg() + "-无法删除");
            }
        }

        getApp().delete(List.of(id));
        if (r.getErrCode() == 20040) {
            //删除学生
            {
                JoinWrapperPlus<EssStudyStudent> query = EssStudyStudentService.getBean().join();
                query.eq("esstu_study_id", entity.getKey());
                EssStudyStudentService.getBean().remove(query);
            }
            //删除任务
            {
                JoinWrapperPlus<EssStudyTask> query = EssStudyTaskService.getBean().join();
                query.eq("estask_study_id", entity.getKey());
                EssStudyTaskService.getBean().remove(query);
            }
            //删除学生明细记录
            {
                JoinWrapperPlus<EssStudyRecord> query = EssStudyRecordService.getBean().join();
                query.eq("esre_study_id", entity.getKey());
                EssStudyRecordService.getBean().remove(query);
            }
        }

        return EnumSys.OK.getR();
    }

    /**
     * 任务标记完成
     *
     * @param vo
     */
    public XReturn studyTaskDone(VoEssStudyTaskDone vo) {
        EssStudyRecord entityRecord = EssStudyRecordService.getBean().getEntity(vo.getRecord_id());
        if (entityRecord == null) {
            return EnumSys.ERR_VAL.getR("id异常");
        }
        if (!entityRecord.getEsre_uid().equals(getUid())) {
            return EnumSys.ERR_VAL.getR("操作用户异常，" + getUid());
        }
        if (entityRecord.getEsre_state() != 0) {
            return XReturn.getR(20279, "任务已完成");
        }
        if ("test1".equals(entityRecord.getEsre_task_key())) {
            if (vo.getRecord_json() == null) {
                return XReturn.getR(20281, "缺少实训答案");
            }

            List<VoEssStudyTaskDoneJsonItem> items = vo.getRecord_json().getItems();
            for (VoEssStudyTaskDoneJsonItem item : items) {
                Collections.sort(item.getQuestion_answer()); //从小到大排序
            }
        }
        EssStudy entityStudy = getApp().getEntity(entityRecord.getEsre_study_id());
        XReturn r = getState(entityStudy);
        if (r.err()) {
            return r;
        }

        return XApp.getTransaction().execute(status -> {
            //更新已完成状态
            EssStudyRecord entityUpdate = new EssStudyRecord();
            entityUpdate.setEsre_id(entityRecord.getEsre_id());
            entityUpdate.setEsre_state(1);
            entityUpdate.setEsre_state_date(LocalDateTime.now());
            if (vo.getRecord_json() != null) {
                entityUpdate.setEsre_state_json(XJson.toJSONString(vo.getRecord_json()));
            }
            EssStudyRecordService.getBean().updateById(entityUpdate);
            //更新已完成总人数
            EssStudyTaskService.getBean().update()
                    .setSql("estask_total_done = estask_total_done + 1")
                    .eq("estask_id", entityRecord.getEsre_task_id())
                    .update();
            //增加学生积分
            EssStudyTask entityTask = EssStudyTaskService.getBean().loadEntity(entityRecord.getEsre_task_id());
            if (entityTask.getEstask_fun() > 0) {
                VaFunAdd vaFunAdd = VaFunAdd.of(entityRecord.getKey()
                        , getUid()
                        , entityRecord.getEsre_study_id()
                        , "app_ess"
                        , entityTask.getEstask_fun().intValue()
                        , "学习任务");
                vaFunAdd.setUpdate_fun(true);
                SvcFun.getBean().add(vaFunAdd);
            }
            //更新学习统计数据
            String type = entityTask.getEstask_key();
            switch (entityTask.getEstask_key()) {
                case "video":
                case "file":
                case "build_sh":
                case "build_video":
                case "build_img":
                case "build_paper":
                    type = "file";
            }
            SvcEssUser.getBean().updateTotal(entityRecord.getEsre_uid(), entityStudy.getEstudy_module_id(), type, 0);

            return EnumSys.OK.getR();
        });
    }

    /**
     * 更新学习数量
     *
     * @param moduleId
     */
    public void updateModuleStudyTotal(String moduleId) {
        JoinWrapperPlus<EssStudy> query = listQuery();
        query.eq("estudy_module_id", moduleId);
        Long count = getApp().count(query);

        EssModule entity = new EssModule();
        entity.setEmod_id(moduleId);
        entity.setEmod_set_task_total(count.intValue());
        SvcEssModule.getApp().updateById(entity);
    }
}
